/* Microsoft Reference Implementation for TPM 2.0
 *
 *  The copyright in this software is being made available under the BSD License,
 *  included below. This software may be subject to other third party and
 *  contributor rights, including patent rights, and no such rights are granted
 *  under this license.
 *
 *  Copyright (c) Microsoft Corporation
 *
 *  All rights reserved.
 *
 *  BSD License
 *
 *  Redistribution and use in source and binary forms, with or without modification,
 *  are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this list
 *  of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice, this
 *  list of conditions and the following disclaimer in the documentation and/or
 *  other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Tpm.h"
#include "ObjectChangeAuth_fp.h"

#if CC_ObjectChangeAuth  // Conditional expansion of this file

#include "Object_spt_fp.h"

/*(See part 3 specification)
// Create an object
*/
//  Return Type: TPM_RC
//      TPM_RC_SIZE             'newAuth' is larger than the size of the digest
//                              of the Name algorithm of 'objectHandle'
//      TPM_RC_TYPE             the key referenced by 'parentHandle' is not the
//                              parent of the object referenced by 'objectHandle';
//                              or 'objectHandle' is a sequence object.
/*
tpm2-tools
tpm2_changeauth - Configures authorization values for the various hierarchies, NV indices, transient and persistent objects.
Note: For non-permanent objects (Transient objects and Persistent objects), copies of the private information (files or persistent handles) 
created prior to changing auth are not invalidated.

Part3, 12.8 TPM2_ObjectChangeAuth
This command is used to change the authorization secret for a TPM-resident object.
If successful, a new private area for the TPM-resident object associated with objectHandle is returned,
which includes the new authorization value.
This command does not change the authorization of the TPM-resident object on which it operates.
Therefore, the old authValue (of the TPM-resident object) is used when generating the response HMAC
key if required.
此命令用于更改 TPM 驻留对象的授权机密。
如果成功，则返回与 objectHandle 关联的 TPM 驻留对象的新私有区域，其中包括新的授权值。
此命令不会更改其运行的 TPM 驻留对象的授权。
因此，如果需要，在生成响应 HMAC 密钥时使用旧的 authValue（TPM 驻留对象的）。

NOTE 1 The returned outPrivate will need to be loaded before the new authorization will apply.
注 1 返回的 outPrivate 需要在新授权应用之前加载。

NOTE 2 The TPM-resident object may be persistent and changing the authorization value of the persistent object could 
prevent other users from accessing the object. This is why this command does not change the TPM-resident object.
注 2：TPM 驻留对象可能是持久的，更改持久对象的授权值可能会阻止其他用户访问该对象。 这就是此命令不更改 TPM 驻留对象的原因。

EXAMPLE If a persistent key is being used as a Storage Root Key and the authorization of the key is a wellknown value so 
that the key can be used generally, then changing the authorization value in the persistent key would deny access to other users.
示例 如果持久密钥被用作存储根密钥并且密钥的授权是众所周知的值以便密钥可以被普遍使用，那么更改持久密钥中的授权值将拒绝其他用户的访问。

This command may not be used to change the authorization value for an NV Index or a Primary Object.
此命令不能用于更改 NV 索引或主要对象的授权值。

NOTE 3 If an NV Index is to have a new authorization, it is done with TPM2_NV_ChangeAuth().
注 3 如果 NV 索引要有新的授权，则使用 TPM2_NV_ChangeAuth() 完成。

NOTE 4 If a Primary Object is to have a new authorization, it needs to be recreated (TPM2_CreatePrimary()).
注 4 如果一个主对象要有一个新的授权，它需要被重新创建（TPM2_CreatePrimary()）。
*/

/*
修改“非”主对象的授权值。
直接修改 in->objectHandle 指向的对象中的授权值（TPMT_SENSITIVE.authValue）,
然后调用  SensitiveToPrivate->ProduceOuterWrap 包装为可导出的外部对象 blob
可见此处的 sensitive 数据是已经加载已解密的敏感数据。
*/
TPM_RC
TPM2_ObjectChangeAuth(
    ObjectChangeAuth_In     *in,            // IN: input parameter list
    ObjectChangeAuth_Out    *out            // OUT: output parameter list
    )
{
    TPMT_SENSITIVE           sensitive;

    OBJECT                  *object = HandleToObject(in->objectHandle);
    TPM2B_NAME               QNCompare;

// Input Validation

    // Can not change authorization on sequence object
    if(ObjectIsSequence(object))
        return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle;

    // Make sure that the authorization value is consistent with the nameAlg
    if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg))
        return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth;

    // Parent handle should be the parent of object handle.  In this
    // implementation we verify this by checking the QN of object.  Other
    // implementation may choose different method to verify this attribute.
    ComputeQualifiedName(in->parentHandle,
                         object->publicArea.nameAlg,
                         &object->name, &QNCompare);
    if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b))
        return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle;

// Command Output
    // Prepare the sensitive area with the new authorization value
    sensitive = object->sensitive;
    sensitive.authValue = in->newAuth;

    // Protect the sensitive area
    SensitiveToPrivate(&sensitive, &object->name, HandleToObject(in->parentHandle),
                       object->publicArea.nameAlg,
                       &out->outPrivate);
    return TPM_RC_SUCCESS;
}

#endif // CC_ObjectChangeAuth